/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.form.palette; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.openide.awt.ToolbarToggleButton; import org.openide.cookies.InstanceCookie; import org.openide.loaders.DataFolder; import org.openide.loaders.InstanceDataObject; import org.openide.loaders.InstanceSupport; import org.openide.nodes.*; import org.openide.util.HelpCtx; import org.openide.util.RequestProcessor; import org.netbeans.modules.form.*; /** * The ComponentPalette is a visual component that manages * a add component/selection mode for FormEditor. * The current state of the palette is returned by getSelectedItem() method. * * @author Ian Formanek, Jan Jancura */ public class ComponentPalette extends JPanel { /** generated Serialized Version UID */ // static final long serialVersionUID = 6131327264550974618L; private final static java.util.ResourceBundle bundle = org.openide.util.NbBundle.getBundle (ComponentPalette.class); private static final int DEFAULT_WIDTH = 420; private static final int MAX_WIDTH = 1024; private static String KEY_PALETTE_MODE = "PALETTE MODE"; // NOI18N private static String KEY_SELECTED_BUTTON = "SELECTED BUTTON"; // NOI18N private static String KEY_SELECTED_PALETTE_ITEM = "SELECTED PALETTE ITEM"; // NOI18N private static ComponentPalette sharedInstance; // ----------------------------------------------------------------------------- // Private variables private NodeListener categoryNodeListener; //private static int mode = PaletteAction.MODE_SELECTION; /** The button that represents Selection mode */ private ToolbarToggleButton selectionButton; /** The button that represents Selection mode */ private ToolbarToggleButton connectionButton; /** Points to the tabbs */ private JTabbedPane tabbedArea = null; /** Provides palette content (Palette categories and palette items). */ private PaletteNode paletteNode; /** A mapping PaletteItem -> ToolbarToggleButton */ private HashMap itemToButton = new HashMap(50); /** A mapping ToolbarToggleButton -> PaletteItem * @associates PaletteItem*/ private HashMap buttonToItem = new HashMap(50); /** A mapping Category Node -> Container in palette containing buttons for items in this category * @associates ScrollPalette*/ private HashMap categoryToPanel = new HashMap (10); // PBUZEK: move into paletteAction shared values: /** The currently selected button */ //private static ToolbarToggleButton selectedButton; /** The currently selected palette node */ //private static PaletteItem selectedPaletteItem = null; private ActionListener buttonListener; /** task that controls the updating of component pallete */ private RequestProcessor.Task refreshTask; /** set of nodes that has to be updated * @associates PaletteCategoryNode*/ private Set refreshNodes = new HashSet (11); /** item that signals that the component is preparing or null */ private JLabel wait; // ----------------------------------------------------------------------------- // Constructors static final long serialVersionUID =7249158494688903041L; /** * Constructs a new empty ComponentPalette. */ public ComponentPalette () { if (sharedInstance == null) { sharedInstance = this; } buttonListener = new ActionListener () { public void actionPerformed (ActionEvent evt) { ToolbarToggleButton pressedButton = (ToolbarToggleButton) evt.getSource(); if (pressedButton == selectionButton) { if (getMode () == PaletteAction.MODE_SELECTION) { setSelectedButton (selectionButton); selectionButton.setSelected (true); return; } setSelectedItem (null); setMode (PaletteAction.MODE_SELECTION); } else if (pressedButton == connectionButton) { if (getMode () == PaletteAction.MODE_CONNECTION) { setSelectedButton (connectionButton); connectionButton.setSelected (true); return; } setSelectedItem (null); setMode (PaletteAction.MODE_CONNECTION); } else { if (getSelectedButton () == pressedButton) { setSelectedItem (null); setMode (PaletteAction.MODE_SELECTION); } else { setSelectedItem ((PaletteItem)buttonToItem.get (evt.getSource ())); setMode (PaletteAction.MODE_ADD); } } } }; paletteNode = PaletteNode.getPaletteNode (); paletteNode.addNodeListener (new NodeAdapter () { public void childrenAdded (NodeMemberEvent evt) { updatePaletteInEventQueue (); } public void childrenRemoved (NodeMemberEvent evt) { updatePaletteInEventQueue (); } public void childrenReordered (NodeReorderEvent evt) { updatePaletteInEventQueue (); } } ); categoryNodeListener = new NodeAdapter () { public void childrenAdded (NodeMemberEvent evt) { updateCategoryInEventQueue ((PaletteCategoryNode)evt.getSource (), 200); } public void childrenRemoved (NodeMemberEvent evt) { updateCategoryInEventQueue ((PaletteCategoryNode)evt.getSource (), 200); } public void childrenReordered (NodeReorderEvent evt) { updateCategoryInEventQueue ((PaletteCategoryNode)evt.getSource (), 200); } public void propertyChange (PropertyChangeEvent evt) { if (Node.PROP_NAME.equals (evt.getPropertyName ()) || Node.PROP_DISPLAY_NAME.equals (evt.getPropertyName ())) { updateCategoryInEventQueue ((PaletteCategoryNode)evt.getSource (), 200); } } }; // create selection button ... setLayout (new BorderLayout ()); JPanel selectionPanel = new JPanel (); selectionPanel.setLayout (new BorderLayout ()); selectionPanel.setBorder (new javax.swing.border.EmptyBorder (3, 3, 3, 3)); selectionButton = new ToolbarToggleButton( new ImageIcon(getClass ().getResource ("/org/netbeans/modules/form/resources/selectionMode.gif")), // NOI18N true); selectionButton.addActionListener(buttonListener); selectionButton.setToolTipText (bundle.getString ("CTL_SelectionButtonHint")); HelpCtx.setHelpIDString (selectionButton, ComponentPalette.class.getName () + ".selectionButton"); // NOI18N selectionPanel.add (selectionButton, BorderLayout.NORTH); connectionButton = new ToolbarToggleButton( new ImageIcon(getClass ().getResource ("/org/netbeans/modules/form/resources/connectionMode.gif")), // NOI18N false); connectionButton.addActionListener(buttonListener); connectionButton.setToolTipText (bundle.getString ("CTL_ConnectionButtonHint")); HelpCtx.setHelpIDString (connectionButton, ComponentPalette.class.getName () + ".connectionButton"); // NOI18N selectionPanel.add (connectionButton, BorderLayout.SOUTH); add (selectionPanel, BorderLayout.WEST); setSelectedButton (selectionButton); HelpCtx.setHelpIDString (this, ComponentPalette.class.getName ()); wait = new JLabel (bundle.getString("MSG_PreparingPalette")); wait.setHorizontalAlignment(SwingConstants.CENTER); add (wait, BorderLayout.CENTER); refreshTask = RequestProcessor.createRequest (new Runnable () { public void run () { Set s = refreshNodes; refreshNodes = new HashSet (11); if (tabbedArea != null) { remove (tabbedArea); } Iterator it = s.iterator (); while (it.hasNext ()) { PaletteCategoryNode node = (PaletteCategoryNode)it.next (); updateCategory (node); } if (wait != null) { remove (wait); wait = null; } add(tabbedArea, BorderLayout.CENTER); invalidate (); validate (); repaint (); } }); refreshTask.setPriority (0); updatePaletteInEventQueue (); } public static ComponentPalette getDefault () { if (sharedInstance == null) { sharedInstance = new ComponentPalette (); } return sharedInstance; } public static DataFolder getPaletteFolder () { return PaletteNode.getPaletteFolder (); } private void updatePaletteInEventQueue () { // it might be invoked from different thread, so we must use invokeLater to perform visual operations EventQueue.invokeLater(new Runnable () { public void run () { updatePalette (); } }); } private void updateCategoryInEventQueue (final PaletteCategoryNode node, int time) { refreshNodes.add (node); refreshTask.schedule (time); } // ----------------------------------------------------------------------------- // Public interface public synchronized String[] getPaletteCategories () { Object[] nodes = categoryToPanel.keySet ().toArray (new PaletteCategoryNode[0]); String[] categoryNames = new String[nodes.length]; for (int i = 0; i < nodes.length; i++) { categoryNames[i] = ((PaletteCategoryNode)nodes[i]).getDisplayName (); } return categoryNames; } public PaletteItem[] getAllItems () { Set itemsSet = itemToButton.keySet (); PaletteItem[] items = new PaletteItem[itemsSet.size ()]; itemsSet.toArray (items); return items; } // ----------------------------------------------------------------------------- // Other methods public Dimension getPreferredSize () { Dimension pref = super.getPreferredSize (); return new Dimension (Math.max (pref.width, DEFAULT_WIDTH), pref.height); } /** * Gets the maximum size of this component. * @return A dimension object indicating this component's maximum size. * @see #getMinimumSize * @see #getPreferredSize * @see LayoutManager */ public Dimension getMaximumSize () { return new Dimension (MAX_WIDTH, super.getPreferredSize ().height); } public Dimension getMinimumSize () { return new Dimension (DEFAULT_WIDTH, super.getPreferredSize ().height); } /** * Repaints palette with datas from paletteContext variable. */ public synchronized void updatePalette () { // if (tabbedArea != null) remove (tabbedArea); // first remove node listeners on existing nodes for (Iterator it = categoryToPanel.keySet ().iterator (); it.hasNext (); ) { PaletteCategoryNode ctg = (PaletteCategoryNode) it.next (); ctg.removeNodeListener (categoryNodeListener); } for (Iterator it = buttonToItem.keySet ().iterator (); it.hasNext (); ) { ((ToolbarToggleButton)it.next ()).removeActionListener (buttonListener); } itemToButton.clear (); buttonToItem.clear (); categoryToPanel.clear (); // Tabbs and switching ........................................... PaletteCategoryNode[] categories = paletteNode.getPaletteCategories (); if (tabbedArea != null) { remove (tabbedArea); } tabbedArea = new JTabbedPane(); tabbedArea.addChangeListener (new ChangeListener () { public void stateChanged (ChangeEvent evt) { if (getMode () == PaletteAction.MODE_ADD) { setSelectedItem (null); // set selection mode if tabs are switched setMode (PaletteAction.MODE_SELECTION); } } } ); // create component categories for (int i = 0; i < categories.length; i++) { // create palette buttons ScrollPalettePanel palette = new ScrollPalettePanel(); palette.setLayout (new FlowLayout (FlowLayout.LEFT)); categories[i].addNodeListener (categoryNodeListener); ScrollPalette sp = new ScrollPalette(palette); categoryToPanel.put (categories[i], sp); tabbedArea.addTab(categories[i].getDisplayName(), sp); int cnt = categories[i].getChildren ().getNodesCount (); updateCategoryInEventQueue (categories[i], cnt == 0 ? 5000 : 500); } /* add(tabbedArea, BorderLayout.CENTER); invalidate (); validate (); repaint (); */ } private void updateCategory (PaletteCategoryNode category) { String newName = category.getDisplayName (); ScrollPalette sp = (ScrollPalette)categoryToPanel.get(category); if (sp == null) return; final Container categoryPanel = (Container)sp.getView (); int tabIndex = tabbedArea.indexOfComponent (sp); // update tab name if necessary // System.out.println ("Index of "+newName+", index: "+tabIndex); // NOI18N if ((tabIndex != -1) && !newName.equals (tabbedArea.getTitleAt (tabIndex))) { tabbedArea.setTitleAt (tabIndex, newName); } Component[] buttons = categoryPanel.getComponents (); for (int i = 0; i < buttons.length; i++) { ((ToolbarToggleButton)buttons[i]).removeActionListener (buttonListener); PaletteItem it = (PaletteItem)buttonToItem.get (buttons[i]); buttonToItem.remove (buttons[i]); itemToButton.remove (it); } Node[] categoryItems = category.getCategoryComponents(); final java.util.List toAdd = new LinkedList (); for (int j = 0; j < categoryItems.length; j++) { Node itemNode = categoryItems[j]; PaletteItem palItem = null; // 1. try InstanceDataObject InstanceDataObject ido = (InstanceDataObject)itemNode.getCookie (InstanceDataObject.class); if (ido != null) { try { palItem = new PaletteItem (ido); } catch (java.io.IOException e) { e.printStackTrace(); // XXX continue; // problems creating -> do not present in palette [PENDING] } catch (ClassNotFoundException e) { e.printStackTrace(); // XXX continue; // problems creating -> do not present in palette [PENDING] } } else { // 2. try InstanceCookie InstanceCookie ic = (InstanceCookie)itemNode.getCookie (InstanceCookie.class); if (ic != null) { try { palItem = new PaletteItem (ic); } catch (java.io.IOException e) { continue; // problems creating -> do not present in palette [PENDING] } catch (ClassNotFoundException e) { continue; // problems creating -> do not present in palette [PENDING] } } else { continue; // not suitable to be presented in palette } } ToolbarToggleButton button = new PaletteButton (itemNode, palItem); button.addActionListener (buttonListener); toAdd.add (button); itemToButton.put (palItem, button); buttonToItem.put (button, palItem); } EventQueue.invokeLater(new Runnable () { public void run () { categoryPanel.removeAll (); Iterator it = toAdd.iterator (); while (it.hasNext ()) { Component comp = (Component)it.next(); categoryPanel.add(comp); } categoryPanel.invalidate (); validate (); repaint (); } }); } private ToolbarToggleButton getSelectedButton () { return (ToolbarToggleButton) PaletteAction.get (PaletteAction.class). getValue (KEY_SELECTED_BUTTON); } private void setSelectedButton (ToolbarToggleButton button) { PaletteAction.get (PaletteAction.class).putValue (KEY_SELECTED_BUTTON, button); } public int getMode () { Integer mode = (Integer) PaletteAction.get (PaletteAction.class).getValue (KEY_PALETTE_MODE); if(mode == null) { return PaletteAction.MODE_SELECTION; } else { return mode.intValue(); } } public void setMode (int newMode) { PaletteAction.get (PaletteAction.class).putValue (KEY_PALETTE_MODE, new Integer (newMode)); switch (newMode) { case PaletteAction.MODE_SELECTION: getSelectedButton ().setSelected (false); setSelectedButton (selectionButton); selectionButton.setSelected (true); setSelectedItem (null); break; case PaletteAction.MODE_CONNECTION: getSelectedButton ().setSelected (false); setSelectedButton (connectionButton); connectionButton.setSelected (true); setSelectedItem (null); org.openide.nodes.Node root = FormEditor.getComponentInspector ().getExplorerManager ().getRootContext (); RADComponentCookie cookie = (RADComponentCookie)root.getCookie (RADComponentCookie.class); if (cookie != null) { FormManager2 man = cookie.getRADComponent ().getFormManager (); man.cancelSelection (); } break; case PaletteAction.MODE_ADD: ToolbarToggleButton newButton = (ToolbarToggleButton) itemToButton.get (getSelectedItem ()); getSelectedButton ().setSelected (false); setSelectedButton (newButton); newButton.setSelected (true); break; } } /** Returns the currently selected PaletteNode (that represents a * JavaBean to be added to the form) or null for selection mode. * @return the currently selected PaletteNode or null for selection mode */ public PaletteItem getSelectedItem () { return (PaletteItem) PaletteAction.get (PaletteAction.class).getValue (KEY_SELECTED_PALETTE_ITEM); } /** Sets the current add component or selection mode. * @param value The new add component or null for selection mode */ public void setSelectedItem (PaletteItem value) { PaletteAction.get (PaletteAction.class).putValue (KEY_SELECTED_PALETTE_ITEM, value); } } /* * Log * 38 Gandalf 1.37 3/7/00 Tran Duc Trung fix #5791: cannot add * serialized bean to component palette * 37 Gandalf 1.36 1/20/00 Libor Kramolis * 36 Gandalf 1.35 1/18/00 Libor Kramolis * 35 Gandalf 1.34 1/15/00 Ian Formanek Bigger default width of * the component palette * 34 Gandalf 1.33 1/13/00 Ian Formanek NOI18N #2 * 33 Gandalf 1.32 1/5/00 Ian Formanek NOI18N * 32 Gandalf 1.31 12/9/99 Jaroslav Tulach #4699 * 31 Gandalf 1.30 11/27/99 Patrik Knakal * 30 Gandalf 1.29 11/24/99 Pavel Buzek static fields moved into * PaletteAction * 29 Gandalf 1.28 11/15/99 Pavel Buzek selectedButton made * static * 28 Gandalf 1.27 11/10/99 Pavel Buzek mode and * selectedPaletteItem properties made static * 27 Gandalf 1.26 11/5/99 Jaroslav Tulach ComponentPalette.getDefault * is back. * 26 Gandalf 1.25 11/4/99 Jaroslav Tulach Component palette is * faster/better/etc. * 25 Gandalf 1.24 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 24 Gandalf 1.23 10/11/99 Ian Formanek Fixed problem with * doubling ComponentPalette tabs * 23 Gandalf 1.22 10/10/99 Ian Formanek Fixed bug 3823 - After * adding a category to the component palette in Global Settings, new tab * does not appear and is unresponsive until it is hidden and reshown. * 22 Gandalf 1.21 7/28/99 Ian Formanek Patched bug where * NullPointerException was sometimes thrown during installing Form Module * 21 Gandalf 1.20 7/20/99 Jesse Glick Context help * (optimization for real this time). * 20 Gandalf 1.19 7/20/99 Jesse Glick Context help * (optimization). * 19 Gandalf 1.18 7/19/99 Jesse Glick Context help. * 18 Gandalf 1.17 7/16/99 Ian Formanek Fixed bug 1855 - * Tooltips of borders in Component Pallete print *BorderInfo probably * instead of *Border . * 17 Gandalf 1.16 6/11/99 Ian Formanek This version is part of * build 337 * 16 Gandalf 1.15 6/10/99 Ian Formanek * 15 Gandalf 1.14 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 14 Gandalf 1.13 6/7/99 Ian Formanek Palette nodes extend * FolderNode * 13 Gandalf 1.12 6/7/99 Ian Formanek Better support of * instances * 12 Gandalf 1.11 6/4/99 Ian Formanek * 11 Gandalf 1.10 5/24/99 Ian Formanek Provided static access * to Palette folder * 10 Gandalf 1.9 5/20/99 Ian Formanek Fixed multiplication of * PaletteItems * 9 Gandalf 1.8 5/14/99 Ian Formanek * 8 Gandalf 1.7 5/11/99 Ian Formanek Build 318 version * 7 Gandalf 1.6 5/4/99 Ian Formanek package change * (formeditor -> ..) * 6 Gandalf 1.5 4/26/99 Ian Formanek * 5 Gandalf 1.4 4/4/99 Ian Formanek Fixed too many * unnecessary revalidations * 4 Gandalf 1.3 4/2/99 Ian Formanek Fixed synchronization * problem causing deadlock during startup * 3 Gandalf 1.2 3/30/99 Ian Formanek Finally nearly works * 2 Gandalf 1.1 3/24/99 Ian Formanek * 1 Gandalf 1.0 3/24/99 Ian Formanek * $ */